<template>
  <div class="app-side">
    <a-menu
      mode="inline"
      v-model:openKeys="openKeys"
      v-model:selectedKeys="selectedKeys"
      @click="handleRoute"
    >
      <div v-for="item in menuList" :key="item.name">
        <MenuTree :menu="item" />
      </div>
    </a-menu>
  </div>
</template>

<script lang="ts">
import { defineComponent, reactive, toRefs } from "vue";
import { useRouter, useRoute, onBeforeRouteUpdate } from "vue-router";
import { baseRouter } from "@/router/modules/index";
import MenuTree from "../menu-tree/index.vue";

export default defineComponent({
  name: "AppLayoutSide",
  components: {
    MenuTree
  },
  setup() {
    const data = reactive({
      openKeys: [], //当前展开的 SubMenu 菜单项 key 数组
      selectedKeys: [] //当前选中的菜单项 key 数组
    });
    // 要在 setup 函数中访问路由，请调用 useRouter 或 useRoute 函数。
    const router = useRouter();
    const route = useRoute();
    const menuList = reactive(baseRouter || []);
    const deepKeys = (path: string, item: any, keys: Array<string>, openKeys: Array<string>) => {
      if (item && item.children && item.children.length) {
        item.children.forEach((row: any) => {
          deepKeys(path, row, keys, openKeys);
        });
        // openKeys 数组里设置的key要跟sub-menu的key保持一致
        openKeys.push(item.name);
      } else {
        if (path.includes(item.path)) {
          keys.push(item.name);
        }
      }
    };
    // 初始化菜单选中
    const initMenu = (menuList: any, to?: any) => {
      const openKeys: any = [];
      const selectedKeys: any = [];
      let path = route.path;
      if (to) {
        path = to.path;
      }
      if (menuList.length) {
        menuList.forEach((item: any) => {
          // 配置打开的菜单项
          deepKeys(path, item, selectedKeys, openKeys);
        });
      }
      data.openKeys = openKeys;
      // console.log("openKeys: ", data.openKeys);
      data.selectedKeys = selectedKeys;
    };
    initMenu(menuList);
    // 点击 MenuItem 调用此函数
    const handleRoute = function (row: any) {
      // 借助 router 的实例方法，通过编写代码来实现路由导航。
      // 替换当前位置，唯一不同的是，它在导航时不会向 history 添加新记录
      router.replace({
        name: row.key
      });
    };
    // 导航守卫，响应路由参数的变化，解决组件声明周期钩子不会被调用问题，及根据参数的变化做出响应
    onBeforeRouteUpdate((to) => {
      initMenu(menuList, to);
    });

    return {
      menuList,
      handleRoute,
      ...toRefs(data)
    };
  }
});
</script>
<style lang="less" scoped>
@import "index.less";
</style>
